package org.locker.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.locker.common.core.exception.ServiceException;
import org.locker.common.core.utils.MapstructUtils;
import org.locker.common.core.utils.StringUtils;
import org.locker.common.mybatis.core.page.TableDataInfo;
import org.locker.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.locker.domain.ManagerFees;
import org.locker.domain.enums.AuditStatusEnum;
import org.locker.domain.enums.WithdrawStatusEnum;
import org.locker.service.IManagerFeesService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.locker.domain.bo.ManagerWithdrawBo;
import org.locker.domain.vo.ManagerWithdrawVo;
import org.locker.domain.ManagerWithdraw;
import org.locker.mapper.ManagerWithdrawMapper;
import org.locker.service.IManagerWithdrawService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * 代理商提现记录Service业务层处理
 *
 * @author winnie
 * @date 2023-10-11
 */
@RequiredArgsConstructor
@Service
public class ManagerWithdrawServiceImpl  extends ServiceImpl<ManagerWithdrawMapper,ManagerWithdraw>  implements IManagerWithdrawService {

    private final ManagerWithdrawMapper baseMapper;
    private final IManagerFeesService feesService;

    /**
     * 查询代理商提现记录
     */
    @Override
    public ManagerWithdrawVo queryById(Long managerWithdrawId){
        return baseMapper.getById(managerWithdrawId);
    }

    /**
     * 查询代理商提现记录列表
     */
    @Override
    public TableDataInfo<ManagerWithdrawVo> queryPageList(ManagerWithdrawBo bo, PageQuery pageQuery) {
        Page<ManagerWithdrawVo> result = baseMapper.listByPage(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    /**
     * 查询代理商提现记录列表
     */
    @Override
    public List<ManagerWithdrawVo> queryList(ManagerWithdrawBo bo) {
        LambdaQueryWrapper<ManagerWithdraw> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ManagerWithdraw> buildQueryWrapper(ManagerWithdrawBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ManagerWithdraw> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getSysUserId() != null, ManagerWithdraw::getSysUserId, bo.getSysUserId());
        lqw.eq(bo.getPositionId() != null, ManagerWithdraw::getPositionId, bo.getPositionId());
        lqw.eq(StringUtils.isNotBlank(bo.getWithdrawNo()), ManagerWithdraw::getWithdrawNo, bo.getWithdrawNo());
        lqw.eq(bo.getWithdrawAmount() != null, ManagerWithdraw::getWithdrawAmount, bo.getWithdrawAmount());
        lqw.eq(bo.getWithdrawTime() != null, ManagerWithdraw::getWithdrawTime, bo.getWithdrawTime());
        lqw.eq(StringUtils.isNotBlank(bo.getWithdrawStatus()), ManagerWithdraw::getWithdrawStatus, bo.getWithdrawStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getWithdrawRemark()), ManagerWithdraw::getWithdrawRemark, bo.getWithdrawRemark());
        lqw.eq(StringUtils.isNotBlank(bo.getAuditStatus()), ManagerWithdraw::getAuditStatus, bo.getAuditStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getAuditRemark()), ManagerWithdraw::getAuditRemark, bo.getAuditRemark());
        return lqw;
    }

    /**
     * 新增代理商提现记录
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(ManagerWithdrawBo bo) {

        ManagerFees one = feesService.getOne(Wrappers.<ManagerFees>lambdaQuery()
            .eq(ManagerFees::getPositionId, bo.getPositionId())
            .eq(ManagerFees::getSysUserId, bo.getSysUserId()));
        //判断可提现金额是否满足当前次提现
        BigDecimal residueAmount = one.getResidueAmount();
        BigDecimal withdrawAmount = bo.getWithdrawAmount();
        if (residueAmount.compareTo(withdrawAmount)==-1){
            throw new ServiceException("剩余可提金额不足!");
        }
        boolean update = feesService.update(Wrappers.<ManagerFees>lambdaUpdate()
            .set(ManagerFees::getResidueAmount, one.getResidueAmount().subtract(withdrawAmount))
            .set(ManagerFees::getFreezeAmount, one.getFreezeAmount().add(withdrawAmount))
            .eq(ManagerFees::getPositionId, bo.getPositionId())
            .eq(ManagerFees::getSysUserId, bo.getSysUserId())
            .eq(ManagerFees::getVersion, one.getVersion()));
        if (!update){
            throw new ServiceException("用户提现-更新用户账户失败!");
        }

        ManagerWithdraw add = MapstructUtils.convert(bo, ManagerWithdraw.class);
        add.setWithdrawNo(IdUtil.getSnowflake().nextIdStr());
        add.setWithdrawTime(DateUtil.date());
        add.setWithdrawStatus(WithdrawStatusEnum.WITHDRAWING.getCode());
        add.setAuditStatus(AuditStatusEnum.WAIT.getCode());
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setManagerWithdrawId(add.getManagerWithdrawId());
        }
        return flag;
    }

    /**
     * 修改代理商提现记录
     */
    @Override
    public Boolean updateByBo(ManagerWithdrawBo bo) {
        ManagerWithdraw update = MapstructUtils.convert(bo, ManagerWithdraw.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean audit(ManagerWithdrawBo bo) {
        Long managerWithdrawId = bo.getManagerWithdrawId();
        String auditStatus = bo.getAuditStatus();
        if (ObjectUtil.isNull(managerWithdrawId) || StrUtil.isBlank(auditStatus)){
            throw new ServiceException("缺少必要参数!");
        }
        ManagerWithdraw withdraw = this.getById(managerWithdrawId);
        Long sysUserId = withdraw.getSysUserId();
        Long positionId = withdraw.getPositionId();
        BigDecimal withdrawAmount = withdraw.getWithdrawAmount();

        ManagerFees managerFees = feesService.getOne(Wrappers.<ManagerFees>lambdaQuery()
            .eq(ManagerFees::getSysUserId, sysUserId)
            .eq(ManagerFees::getPositionId, positionId));

        if (ObjectUtil.isNull(managerFees)){
            throw new ServiceException("对应用户的账号已不存在!");
        }

        if (ObjectUtil.isNull(withdraw)){
            throw new ServiceException("提现记录不存在!");
        }

        if (!AuditStatusEnum.WAIT.getCode().equals(withdraw.getAuditStatus())){
            throw new ServiceException("该提现记录所处状态不能审批操作!");
        }

        withdraw.setAuditStatus(auditStatus);
        withdraw.setAuditRemark(bo.getAuditRemark());
        //释放冻结金额
        LambdaUpdateWrapper<ManagerFees> feesLambdaUpdateWrapper = Wrappers.<ManagerFees>lambdaUpdate()
            .set(ManagerFees::getFreezeAmount,managerFees.getFreezeAmount().subtract(withdrawAmount))
            .eq(ManagerFees::getManagerFeesId, managerFees.getManagerFeesId())
            .eq(ManagerFees::getVersion,managerFees.getVersion());
        if (AuditStatusEnum.PASS.getCode().equals(auditStatus)) {
            //通过逻辑
            withdraw.setWithdrawStatus(WithdrawStatusEnum.WITHDRAW_SUCCESS.getCode());
        }

        if (AuditStatusEnum.REFUSE.getCode().equals(auditStatus)) {
            //拒绝逻辑
            withdraw.setWithdrawStatus(WithdrawStatusEnum.FAIL.getCode());
            //将冻结金额放到可提金额
            feesLambdaUpdateWrapper.set(ManagerFees::getResidueAmount,managerFees.getResidueAmount().add(withdrawAmount));
        }

        boolean update = feesService.update(feesLambdaUpdateWrapper);
        if (!update) {
            throw new ServiceException("提现审批-更新用户账户金额信息失败!");
        }

        this.updateById(withdraw);
        return true;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ManagerWithdraw entity){
        //做一些数据校验,如唯一约束
    }

    /**
     * 批量删除代理商提现记录
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }
}
